package org.showminifier.core;

import java.io.InputStreamReader;
import java.net.URL;

import java.util.logging.Logger;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.tools.shell.Global;

/**
*
* Show Minifier
* Author: Shihua Ma <beijing.josh@gmail.com>
* Copyright (c) 2010 Shihua Ma
* Licensed under the MIT license.
*
*/

public class HtmlEngine {
	
	private static final Logger logger = Logger.getLogger(HtmlEngine.class.getName());

    
    private Context cx;
    private Scriptable scope;
    private Function cp;
    private Function cu;
    private static HtmlEngine engine = null;
    
	public HtmlEngine(){
		try {
        	logger.info("Initializing HtmlEngine");
        	cx = Context.enter();
        	cx.setOptimizationLevel(-1);
        	Global global = new Global();
            global.init(cx);
            scope = cx.initStandardObjects(global);
            URL htmlparser = getClass().getClassLoader().getResource("META-INF/htmlparser.js");
        	URL htmlminifier = getClass().getClassLoader().getResource("META-INF/htmlminifier.js");
        	URL htmllint = getClass().getClassLoader().getResource("META-INF/htmllint.js");
        	URL engine = getClass().getClassLoader().getResource("META-INF/engine.js");
        	//ScriptableObject.putProperty(scope, "options",((Context) cp).javaToJS(options,scope));
    		cx.evaluateReader(scope, new InputStreamReader(htmlparser.openConnection().getInputStream()), htmlparser.getFile(), 1, null);
    		cx.evaluateReader(scope, new InputStreamReader(htmlminifier.openConnection().getInputStream()), htmlminifier.getFile(), 1, null);
    		cx.evaluateReader(scope, new InputStreamReader(htmllint.openConnection().getInputStream()), htmllint.getFile(), 1, null);
    		cx.evaluateReader(scope, new InputStreamReader(engine.openConnection().getInputStream()), engine.getFile(), 1, null);
    		cp = (Function) scope.get("parserHTML", scope);
    		cu = (Function) scope.get("parserURL", scope);
    		//Context.exit();
		} catch (Exception e) {
			logger.warning("HtmlEngine intialization failed:"+ e.getMessage());
		}
	}
	

	public String parser(String input,Options options,URL url) throws MinifierException {
        try {
        	Object	wrapped = cx.javaToJS(options, scope);
        	if(options.isEmbedLint()){
        		options.setLint(cx.newObject(scope, "HTMLLint"));
        	}
        	long time = System.currentTimeMillis();       	
            String result = call(cp, new Object[] {input,wrapped});
            logger.info("The compilation of url[" + url + "] took " + (System.currentTimeMillis () - time) + " ms.");
            return result;
		} catch (Exception e) {
			logger.warning("HtmlEngine parser failed of url[" + url + "]:"+ e.getMessage());
			throw new MinifierException(e.getMessage());
		}finally{
			Context.exit();
		}
	 }
	
	private synchronized String call(Function fn, Object[] args) {
		return (String) Context.call(null, fn, scope, scope, args);
	}
	
	
}
